package com.intel.factorytest.activity;

import static android.location.GpsStatus.GPS_EVENT_FIRST_FIX;
import static android.location.GpsStatus.GPS_EVENT_SATELLITE_STATUS;
import static android.location.GpsStatus.GPS_EVENT_STARTED;
import static android.location.GpsStatus.GPS_EVENT_STOPPED;
import static android.location.LocationProvider.AVAILABLE;
import static android.location.LocationProvider.OUT_OF_SERVICE;
import static android.location.LocationProvider.TEMPORARILY_UNAVAILABLE;

import java.io.FileWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.PendingIntent;
import android.content.Context;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

import com.intel.factorytest.R;
import com.intel.factorytest.cfparser.ConfigFileParseUtil;
import com.intel.factorytest.cfparser.concrete.AConfigFileParser;
import com.intel.factorytest.cfparser.concrete.PropertiesConfParser;
import com.intel.factorytest.util.PropertiesUtil;

public class GPSHot extends BaseActivity {

    private static final String TAG = "GpsTestHot";
    private static final boolean VERBOSE = false;
    private static final String TIMEOUT = "GPS_Timeout";
    private int timeout = 120;
    private boolean isTimeout = false;
    
    private Button mSucBtn;
    private Button mFaiBtn;
    private Button mRepBtn;

    private static final int UPDATEUNKNOW = 0;
    private static final int UPDATEALL = 1;
    private static final int UPDATELOCATION = 2;
    private static final int UPDATESVINFO = 3;
    private static final int UPDATENMEA = 4;
    private static final int UPDATEADDITIONAL = 5;

    private GpsStatus.NmeaListener mNmealsr = null;
    private GpsStatus.Listener mSvLsr = null;
    private LocationListener mLocLsr = null;

    private String mLocInfo = "";
    private String mNmeaInfo = "";
    private String mSvInfo = "";
    private String mTTFF = "";
    private static String mAdditional = "";
    private static int mUpdateType = UPDATEUNKNOW; 
    private TextView mContent;
    private TextView mTimeText = null;

    private static final String CURRENTPROVIDER = "gps";

    //Proximity Alert    
    private PendingIntent mPendingIntent;
    private static final String KEY_PROXIMITY_ENTERING = "enter";
    private static final String OUT_OF_AREA_ACTION = "ANDROID.LOCATION";

    private FileWriter filewriter = null;
    private Context mContext;
    
    private LocationManager mLocMgr = null;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        mContext= this;
        setContentView(R.layout.gpstest);
        initView();
        mSucBtn = (Button) findViewById(R.id.success_button);
        mSucBtn.setVisibility(View.INVISIBLE);

        mTimeText = (TextView) findViewById(R.id.time); 
        //mTimeText.setTextSize(24);
        mContent = (TextView) findViewById(R.id.textview);
        //mContent.setTextSize(24);
        mLocMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        
        if (mLocMgr.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
            //
        }else{
            Settings.Secure.setLocationProviderEnabled(getContentResolver(),LocationManager.GPS_PROVIDER, true);
        }
        
        Timer_Create();
        timeout = getTimeoutLimite();
        RunAll();
        checkTimeout();
    }
    
    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onPause() {
        super.onPause();
        //RemoveListener();
        //Log.d(TAG, "onPause");
        //finish();
        // no more keep screen when work done
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    public void onResume() {
        super.onResume();
        // keep screen on when we work
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mItemTestFinish = true;//add by wangsm
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        RemoveListener();
        Log.d(TAG, "onDestroy");
    }

    private void RemoveListener() {

        Log.d(TAG, "Remove listeners");
        try {
            if(mLocLsr != null)
                mLocMgr.removeUpdates(mLocLsr);
            if(mSvLsr != null)
                mLocMgr.removeGpsStatusListener(mSvLsr);
            if(mNmealsr != null)
                mLocMgr.removeNmeaListener(mNmealsr);

        } catch (IllegalArgumentException ex) {
            PrintError(ex.getMessage());
        }
    }

    private void RunAll() {

        PrintProgress(getString(R.string.SERVICEMENU_GPS_LOADING_TXT));
        mUpdateType = UPDATEALL;
        RemoveListener();
        LocationHandler();
        SvHandler();
//        NmeaHandler();
    }

    private void LocationHandler() {

        InitLocLsn();
        if(mLocLsr == null) {
            PrintError(GPSHot.this.getString(R.string.SERVICEMENU_GPS_ERROR_TXT));
            return;
        }
        try {
            Log.d(TAG,"Location success " + mLocMgr.isProviderEnabled(CURRENTPROVIDER));
            if(mLocMgr.isProviderEnabled(CURRENTPROVIDER) == false)
                Settings.Secure.setLocationProviderEnabled(mContext.getContentResolver(),
                        LocationManager.GPS_PROVIDER, true);
            mLocMgr.requestLocationUpdates(CURRENTPROVIDER, 0, 0, mLocLsr);
        } catch (SecurityException ex) {
            PrintError(ex.getMessage());
        } catch (IllegalArgumentException ex) {
            PrintError(ex.getMessage());
        } catch (RuntimeException ex) {
            PrintError(ex.getMessage());
        }
    }

    private void InitLocLsn() {
        mLocLsr = new  LocationListener() {

            public void onLocationChanged(Location location) {
                Log.d(TAG,"Location changed: " + location);
                if (null == location) {
                    PrintError("Location is NULL, should not be display");
                } else{
                    Print(location);
                }
            }

            public void onProviderDisabled(String provider) {

                Log.d(TAG, "Disabled" + provider + "provider"); 
                if(provider == CURRENTPROVIDER)
                    Settings.Secure.setLocationProviderEnabled(mContext.getContentResolver(),
                            LocationManager.GPS_PROVIDER, true);
            }

            public void onProviderEnabled(String provider) {

                Log.d(TAG, "Enable" + provider + "provider");
                PrintProgress("Starting...");
            }   

            public void onStatusChanged(String provider, int status, Bundle extras) {

                Log.d(TAG, "Status changed: " + status);
                if(provider != CURRENTPROVIDER) {
                    PrintError("provider status changed, but it is not gps provider,ignore it");
                    return;
                }

                switch (status) {
                    case OUT_OF_SERVICE:
                        PrintError("Gps provider status is out of service"); 
                        break;
                    case TEMPORARILY_UNAVAILABLE:
                        PrintError("Gps provider status is temporarily unavailable");
                        break;
                    case AVAILABLE:

                        break;
                }
                //TODO deal extras

            }
        };
    }

    private void SvHandler() {

        InitSvLsn();
        try {

            if(mSvLsr == null || mLocMgr.addGpsStatusListener(mSvLsr) == false) { 
                PrintError("GpsStatus listener can not be loaded");
                Log.d(TAG, "Fail to add Gps Status listener");
            } else
                Log.d(TAG, "Add Gps Status listener success");
        } catch (SecurityException ex) {
            PrintError(ex.getMessage());
        } catch (IllegalArgumentException ex) {
            PrintError(ex.getMessage());
        } catch (RuntimeException ex) {
            PrintError(ex.getMessage()); 
        }
    }

    private void NmeaHandler() {

        InitNmeaLsn();
        try{
            if(mNmealsr == null || mLocMgr.addNmeaListener(mNmealsr) == false){ 
                PrintError("Nmea listener can not be created");
                Log.d(TAG, "Fail to add Nmea listener ");
            } else
                Log.d(TAG, "Add Nmea listener success");

        } catch (SecurityException ex) {
            PrintError(ex.getMessage());
        } catch (IllegalArgumentException ex) {
            PrintError(ex.getMessage());
        } catch (RuntimeException ex) {
            PrintError(ex.getMessage()); 
        }

    }

    private void InitNmeaLsn() {

        mNmealsr = new GpsStatus.NmeaListener() {

            int iCount = 1;
            int iStcSize = 3;
            String sNmea = "";

            public void onNmeaReceived(long timestamp, String nmea) {
                Log.d(TAG, "Update Nmea Sentence:" + timestamp);
                if (null == nmea) {
                    PrintError("NMEA sentence is null");

                } else {

                    if( mUpdateType == UPDATENMEA )
                        iStcSize = 5;

                    /*
                       if( iCount <= iStcSize) {

                       sNmea += "Nmea timestamp: " + String.valueOf(timestamp) + "\n";
                       sNmea += "Nmea sentence: " + nmea + "\n";
                       } else { 

                       Print(sNmea);
                       sNmea = "";
                       iCount = 0;
                       }
                       */


                    if (iStcSize <= iCount) {
                        sNmea = "";
                        iCount = 0;
                    }
                    sNmea += "Nmea timestamp: " + String.valueOf(timestamp) + "\n";
                    sNmea += "Nmea sentence: " + nmea + "\n";
                    Print(sNmea);
                    iCount++;
                }
            }
        };
    }

    private void InitSvLsn() {

        mSvLsr = new GpsStatus.Listener() {

            public void onGpsStatusChanged(int event) {

                Log.d(TAG, "Gps status changed:" + event);
                GpsStatus status = mLocMgr.getGpsStatus(null);
                switch (event) {
                    case GPS_EVENT_STARTED:
                        break;
                    case GPS_EVENT_STOPPED:
                        break;
                    case GPS_EVENT_FIRST_FIX:
                        int ttff = status.getTimeToFirstFix();
                        mTTFF = "TTFF/MiliSec: " + String.valueOf(ttff) + "\n";
                        break;
                    case GPS_EVENT_SATELLITE_STATUS:
                        Print(status.getSatellites());
                        break;
                }
            }
        };
    }

    private void PrintError(String str){
        mContent.setText(str + "\n");
    }
    
    private int count = 0;
    private int msecond = 0;
    private TimerTask t_task = null;
    private Timer timer = new Timer();
    private void Timer_Create()
    {
        t_task = new TimerTask(){
            public void run()
            {    
            m_handler.sendEmptyMessage(count);
            count++;
            msecond++;
            
            if(count == 3)count = 0;
            }
        };
            timer.schedule(t_task , 0, 1000);
    }
    
    Handler m_handler = new Handler()
    {
        public void handleMessage(Message msg) {
            int minute = msecond / 60;
            int second = msecond % 60;
            switch (msg.what)
            {
                case 0:
                    if(minute == 0) {
                        mTimeText.setText(GPSHot.this.getString(R.string.SERVICEMENU_GPS_LOADING_TXT) + ".  " + second + GPSHot.this.getString(R.string.SERVICEMENU_GPS_SECOND_TXT));
                    } else {
                        mTimeText.setText(GPSHot.this.getString(R.string.SERVICEMENU_GPS_LOADING_TXT) + ".  "  + minute + GPSHot.this.getString(R.string.SERVICEMENU_GPS_MINUTE_TXT) + second + GPSHot.this.getString(R.string.SERVICEMENU_GPS_SECOND_TXT));

                    }
                    break;
                case 1:
                    if(minute == 0) {
                        mTimeText.setText(GPSHot.this.getString(R.string.SERVICEMENU_GPS_LOADING_TXT) + ".. " + second + GPSHot.this.getString(R.string.SERVICEMENU_GPS_SECOND_TXT));
                    } else {
                        mTimeText.setText(GPSHot.this.getString(R.string.SERVICEMENU_GPS_LOADING_TXT) + ".. "  + minute + GPSHot.this.getString(R.string.SERVICEMENU_GPS_MINUTE_TXT) + second + GPSHot.this.getString(R.string.SERVICEMENU_GPS_SECOND_TXT));

                    }
                    break;
                case 2:
                    if(minute == 0) {
                        mTimeText.setText(GPSHot.this.getString(R.string.SERVICEMENU_GPS_LOADING_TXT) + "..." + second + GPSHot.this.getString(R.string.SERVICEMENU_GPS_SECOND_TXT));
                    } else {
                        mTimeText.setText(GPSHot.this.getString(R.string.SERVICEMENU_GPS_LOADING_TXT) + "..."  + minute + GPSHot.this.getString(R.string.SERVICEMENU_GPS_MINUTE_TXT) + second + GPSHot.this.getString(R.string.SERVICEMENU_GPS_SECOND_TXT));

                    }
                    break;
            }
            
            if (msecond >= timeout) {
                isTimeout = true;
            }

        }
    };
    
    private int getTimeoutLimite() {
        PropertiesConfParser parser = (PropertiesConfParser) ConfigFileParseUtil.getConfParserConcrete(this, AConfigFileParser.EXTENSION_PROPERTISE);
        PropertiesUtil properties = parser.getProperties(isPcba);
        String timeout_pro = properties.getProperty(TIMEOUT, "120");
        try {
            timeout = Integer.parseInt(timeout_pro);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return timeout;
    }

    private void Print(Location l) {
        
        mSucBtn.setVisibility(View.VISIBLE);

        if(l == null)
            l = new Location(CURRENTPROVIDER);
        t_task.cancel();
        mLocInfo = "";
        mLocInfo += "longitude: " + String.valueOf(l.getLongitude()) + "\n";
        mLocInfo += "latitude: " + String.valueOf(l.getLatitude()) + "\n";
        mLocInfo += "altitude: " + String.valueOf(l.getAltitude()) + "\n";
        mLocInfo += "speed: " + String.valueOf(l.getSpeed()) + "\n";
        mLocInfo += "bearing: " + String.valueOf(l.getBearing()) + "\n";
        mLocInfo += "time/MiliSec: " + String.valueOf(l.getTime()) + "\n";
        mLocInfo += "accuracy: " + String.valueOf(l.getAccuracy()) + "\n";
        UpdateContent();
    }

    private void Print(Iterable<GpsSatellite> g) {
        Log.d(TAG, "GpsSatellite=" + g);
        if (g ==null) { 
            return;
        }
        mSvInfo = "";
        int m = 0;
        for (Iterator<GpsSatellite> iter = g.iterator(); iter.hasNext(); m++) {
            mSucBtn.setVisibility(View.VISIBLE);
            GpsSatellite satellite = iter.next();
            mSvInfo += String.valueOf(m + 1) + ": ";
            mSvInfo += "PRN " + String.valueOf(satellite.getPrn()) + ", ";
            mSvInfo += "SNR: " + String.valueOf(satellite.getSnr()) + ", ";
            mSvInfo += "Azimuth: " + String.valueOf(satellite.getAzimuth()) + ", ";
            mSvInfo += "ElevationAngle: " + String.valueOf(satellite.getElevation()) + "\n";

        }
        Log.d(TAG, "GpsSatellite m = " + m);
        UpdateContent();
    }

    private void Print(String s) {
        mSucBtn.setVisibility(View.VISIBLE);
        mNmeaInfo = "";
        mNmeaInfo = s;
        UpdateContent();
    }

    private void Print(Location l, List<String> lP, List<String> lAP) {
        mSucBtn.setVisibility(View.VISIBLE);
        mAdditional = "";
        mAdditional += "----------The Last known location----------\n";
        if(l == null)
            mAdditional += "No last known location\n";
        else {
            mAdditional += "longitude: " + String.valueOf(l.getLongitude()) + "\n";
            mAdditional += "latitude: " + String.valueOf(l.getLatitude()) + "\n";
            mAdditional += "altitude: " + String.valueOf(l.getAltitude()) + "\n";
            mAdditional += "speed: " + String.valueOf(l.getSpeed()) + "\n";
            mAdditional += "bearing: " + String.valueOf(l.getBearing()) + "\n";
            mAdditional += "time/MiliSec: " + String.valueOf(l.getTime()) + "\n";
            mAdditional += "accuracy: " + String.valueOf(l.getAccuracy()) + "\n";
        }

        mAdditional += "-----------All Enable Providers----------\n";
        for(String s : lP) {
            mAdditional += s+"\n";
        }

        mAdditional += "----------All Known Providers----------\n";
        for(String s : lAP) {
            mAdditional += s+"\n";
        }

        UpdateContent();
    }

    private void PrintProgress(String s) {

        mTimeText.setText(s + "...");
    }

    private void UpdateContent() {
        String tmpstr = "";
        switch(mUpdateType) {
            case UPDATEALL:
                tmpstr = mTTFF + mLocInfo + mSvInfo + mNmeaInfo;
                if(!tmpstr.equals("")) {
                    mContent.setText(tmpstr);
                }
                break;
            case UPDATELOCATION:
                tmpstr = mTTFF + mLocInfo;
                if(!tmpstr.equals("")) {
                    mContent.setText(tmpstr);
                }
                break;
            case UPDATESVINFO:
                tmpstr = mTTFF+mSvInfo;
                if(!tmpstr.equals("")) {
                    mContent.setText(tmpstr);
                }
                break;
            case UPDATENMEA:
                tmpstr = mNmeaInfo;
                if(!tmpstr.equals("")) {
                    mContent.setText(tmpstr);
                }
                break;
            case UPDATEADDITIONAL:
                tmpstr = mAdditional;
                if(!tmpstr.equals("")) {
                    mContent.setText(tmpstr);
                }
                break;
            default:
                PrintError("update content type is unavailable");
                break;
        }

    }
    private void deleteAidingData() {
        mLocMgr.sendExtraCommand(LocationManager.GPS_PROVIDER,
                "delete_aiding_data", null);
        Log.d(TAG, "Delete aiding data");
    }

    @Override
    public void finish() {
        tc.setTestResult(is_pass);
        setTestResult();
        super.finish();
    }
    
    private Handler mHandler_timeout = new Handler() {
        private boolean isFinished = false;
        public void handleMessage(Message msg) {
            if (isTimeout && !isFinished) {
                is_pass = false;
                isFinished = true;
                finish();
            }
        };
    };
    
    private Timer mTimer_Timeout = new Timer();
    private TimerTask mTask_Timeout = new TimerTask() {
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            mHandler_timeout.sendEmptyMessage(0);
        }
    };
    
    private void checkTimeout() {
        mTimer_Timeout.schedule(mTask_Timeout, 1000, 1000);
    }
    
}

